package tp.pr4;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Scanner;

import tp.pr4.gui.MainWindow;
import tp.pr4.gui.NavigationPanel;
import tp.pr4.gui.RobotPanel;
import tp.pr4.instructions.Instruction;
import tp.pr4.instructions.exceptions.InstructionExecutionException;
import tp.pr4.instructions.exceptions.WrongInstructionFormatException;
import tp.pr4.items.ItemContainer;

/**
 * This class represents the robot engine. It controls robot movements by 
 * processing the instructions introduced with the keyboard. The engine 
 * stops when the robot arrives at the space ship, runs out of fuel or 
 * receives a quit instruction.
 *
 * The robot engine is also responsible for updating the fuel level and 
 * the recycled material according to the actions that the robot performs 
 * in the city.
 *
 * The robot engine also contains an inventory where the robot stores the 
 * items that it collects from the city
 * @author Alvaro Saez Hernando
 * @author Noel Clemente Montero 
 */
public class RobotEngine {

	private static final String LINE_SEPARATOR = System.lineSeparator();
	private boolean fin = false;
	private int fuel;
	private int recycledMaterial;
	private ItemContainer container;
	private NavigationModule navMod;
	private static int startingFuel = 100;
	
	

	/**
	 * Creates the robot engine in an initial place, facing at an initial direction and with a city map.
	 * @param initialPlace The place where the robot starts
	 * @param direction The initial direction where the robot is facing at.
	 * @param cityMap The city map as an array of streets
	 */
	public RobotEngine(City cityMap,Place initialPlace, Direction dir){
		this.fin = false;
		this.fuel = startingFuel;
		this.recycledMaterial = 0;
		this.container = new ItemContainer();
		this.navMod = new NavigationModule(cityMap,initialPlace);
	}
	
	/**
	 * It executes an instruction.
	 * The instruction must be configured with the context before executing it. 
	 * It controls the end of the simulation. 
	 * If the execution of the instruction throws an exception, then the corresponding message is printed
	 * @param c The instruction to be executed
	 */
	public void communicateRobot(Instruction c){
		try {
			c.configureContext(this, navMod, container);
			c.execute();
			if((this.navMod.atSpaceship())||(this.fuel==0)){
				requestQuit();
			}
		} catch (InstructionExecutionException e) {
			System.out.print(e.getMessage());
		}
	}
	
	/**
	 * Requests the end of the simulation
	 */
	public void requestQuit(){
		this.fin=true;
	}
	
	/**
	 * Increases the amount of recycled material of the robot
	 * @param weight Amount of recycled material
	 */
	public void addRecycledMaterial ( int weight ){
		
		this.recycledMaterial += weight;
		
	}
	
	/**
	 * Adds an amount of fuel to the robot (it can be negative)
	 * @param fuel Amount of fuel added to the robot
	 */
	public void addFuel (int fuel){
		
		this.fuel += fuel;
		if(this.fuel < 0){
			this.fuel = 0;
		}
		
	}
	
	/**
	 * It starts the robot engine. Basically, it reads a line, the interpreter 
	 * generates the corresponding instruction and executes it. The simulation 
	 * finishes when the robot arrives at the space ship, the user types "QUIT", 
	 * or the robot runs out of fuel
	 */
	public void startEngine(){
		String read;
		Scanner in = new Scanner(System.in);
		this.navMod.scanCurrentPlace();
		this.navMod.getCurrentHeading();
		System.out.print("WALL·E is looking at direction " + this.navMod.getCurrentHeading().toString() + LINE_SEPARATOR);
		printRobotState();
		while(!fin){
				System.out.print("WALL·E> ");
				read = in.nextLine();
				try {
					Instruction instruction = Interpreter.generateInstruction(read);
					communicateRobot(instruction);
				} catch (WrongInstructionFormatException e) {
					System.out.println(e.getMessage());
				}
		}
		in.close();
	}
	
	/**
	 * Prints the information about all possible instructions
	 */
	public void requestHelp() {
		System.out.println(Interpreter.interpreterHelp());	
	}
	
	/**
	 * Prints the state of the robot
	 */
	public void printRobotState(){
		System.out.print("      * My power is " + this.fuel + LINE_SEPARATOR );
		System.out.print("      * My reclycled material is " + this.recycledMaterial + LINE_SEPARATOR);
	}
	
	/**
	 * Return fuel
	 * @return fuel
	 */
	public int getFuel(){
		return this.fuel;
	}
	
	/**
	 * Return recycled material
	 * @return recycled material
	 */
	public int getRecycledMaterial(){
		return this.recycledMaterial;
	}
	
	public void setNavigationPanel(NavigationPanel navPanel){
		
	}
	
	public void setRobotPanel(RobotPanel robotPanel){
		
	}
	
	public void setGUIWindow(MainWindow mainWindow){
		
		
	}
	
}
